home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Demos / DuelVoice / duel.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  17.7 KB  |  534 lines

  1. //-----------------------------------------------------------------------------
  2. // File: Duel.cpp
  3. //
  4. // Desc: Multi-player game
  5. //
  6. // Copyright (C) 1995-2001 Microsoft Corporation. All Rights Reserved.
  7. //-----------------------------------------------------------------------------
  8. #include "duel.h"
  9. #include "gameproc.h"
  10. #include "gfx.h"
  11. #include "DPUtil.h"
  12. #include "diutil.h"
  13. #include "dsutil.h"
  14. #include "lobby.h"
  15.  
  16.  
  17.  
  18. //-----------------------------------------------------------------------------
  19. // Globals
  20. //-----------------------------------------------------------------------------
  21. // This GUID allows DirectPlay to find other instances of the same game on
  22. // the network.  So it must be unique for every game, and the same for 
  23. // every instance of that game.  // {88789F50-0BDB-43b4-AF06-F951EC05D6CE}
  24. GUID g_AppGUID = { 0x88789f50, 0xbdb, 0x43b4, { 0xaf, 0x6, 0xf9, 0x51, 0xec, 0x5, 0xd6, 0xce } };
  25.  
  26. extern DWORD          g_dwFrameCount;
  27. extern DWORD          g_dwFrameTime;
  28. extern int            g_nProgramState;
  29. extern SHIP           g_OurShip;
  30. extern DPID           g_LocalPlayerDPID;
  31.  
  32. static BOOL           g_bReinitialize; // Used for switching display modes
  33.  
  34. TCHAR     g_strAppName[256] = "Duel";               // The name of the sample
  35. HANDLE    g_hDPMessageEvent = NULL;                 // Not used in this sample, needed for DPConnect.cpp
  36. TCHAR     g_strLocalPlayerName[MAX_PLAYER_NAME];    // Local player name
  37. TCHAR     g_strSessionName[MAX_SESSION_NAME];       // Default session name
  38. TCHAR     g_strPreferredProvider[MAX_SESSION_NAME]; // Default preferred provider
  39.  
  40. LPDPLCONNECTION    g_pDPLConnection = NULL;  
  41. LPDIRECTPLAYLOBBY3 g_pDPLobby       = NULL;  
  42.  
  43. HWND      g_hwndMain;             // Main application window handle
  44. HKEY      g_hDuelKey = NULL;      // Duel registry key handle
  45. HINSTANCE g_hInst;                // Application instance handle        
  46. BOOL      g_bShowFrameCount=TRUE; // Show FPS ?
  47. BOOL      g_bIsActive;            // Is the application active ?
  48. BOOL      g_bHostPlayer;          // Are we hosting or joining a game       
  49. DWORD     g_dwKeys;               // User keyboard input
  50. DWORD     g_dwOldKeys;            // Last frame's keyboard input
  51. BOOL      g_bFullscreen=FALSE;    // Window or FullScreen mode ?
  52. RECT      g_rcWindow;             // client rectangle of main window
  53. BOOL      g_bReliable;            // sends are reliable
  54. BOOL      g_bAsync;               // asynchronous sends
  55. BOOL      g_bAsyncSupported;      // asynchronous sends supported
  56. BOOL      g_bUseProtocol;         // DirectPlay Protocol messaging
  57.  
  58.  
  59.  
  60.  
  61. //-----------------------------------------------------------------------------
  62. // Function prototypes
  63. //-----------------------------------------------------------------------------
  64. extern int     DPConnect_StartDirectPlayConnect( HINSTANCE hInst, BOOL bBackTrack = FALSE );
  65. extern HRESULT DPConnect_CheckForLobbyLaunch( BOOL* pbLaunchedByLobby );
  66.  
  67. LRESULT CALLBACK MainWndproc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
  68. HRESULT InitApplication( HINSTANCE hInst );
  69. HRESULT ReadRegKey( HKEY hKey, TCHAR* strName, TCHAR* strValue, DWORD dwLength, TCHAR* strDefault );
  70. HRESULT WriteRegKey( HKEY hKey, TCHAR* strName, TCHAR* strValue );
  71. VOID    CleanupApplication();
  72. BOOL    WasLaunchedByLobby();
  73. BOOL    FinishLobbyLaunch();
  74. VOID    DoHelp();
  75.  
  76.  
  77.  
  78.  
  79. //-----------------------------------------------------------------------------
  80. // Name: WinMain()
  81. // Desc:
  82. //-----------------------------------------------------------------------------
  83. int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int )
  84. {
  85.     MSG     msg;
  86.     BOOL    bLaunchedByLobby;
  87.     HRESULT hr;
  88.  
  89.     g_hInst = hInstance;
  90.  
  91.     // Read information from registry
  92.     RegCreateKeyEx( HKEY_CURRENT_USER, DUEL_KEY, 0, NULL,
  93.                     REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, 
  94.                     &g_hDuelKey, NULL );
  95.  
  96.     ReadRegKey( g_hDuelKey, "Player Name", 
  97.                 g_strLocalPlayerName, MAX_PLAYER_NAME, "" );
  98.     ReadRegKey( g_hDuelKey, "Session Name", 
  99.                 g_strSessionName, MAX_SESSION_NAME, "" );
  100.     ReadRegKey( g_hDuelKey, "Preferred Provider", 
  101.                 g_strPreferredProvider, MAX_SESSION_NAME, "" );
  102.  
  103.     CoInitialize( NULL );
  104.  
  105.     if( FAILED( InitApplication( hInstance ) ) )
  106.         return 0;
  107.  
  108.     // See if we were launched from a lobby server
  109.     hr = DPConnect_CheckForLobbyLaunch( &bLaunchedByLobby );
  110.     if( FAILED(hr) )
  111.         return 1;
  112.  
  113.     if( bLaunchedByLobby )
  114.     {
  115.         // Start game
  116.         PostMessage( g_hwndMain, UM_LAUNCH, 0, 0 );
  117.         g_bIsActive = TRUE;
  118.     }
  119.  
  120.     g_dwFrameTime = timeGetTime();
  121.  
  122.     while( TRUE )
  123.     {
  124.         if( g_bIsActive )
  125.         {
  126.             // Any windows messages ? (returns immediately)
  127.             if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
  128.             {
  129.                 if( !GetMessage( &msg, NULL, 0, 0 ) )
  130.                     break;
  131.  
  132.                 TranslateMessage( &msg );
  133.                 DispatchMessage( &msg );
  134.             }
  135.             else
  136.             {
  137.                 // Poll our receive queue. Polling is used in the sample only for simplicity.
  138.                 // Receiving messages using an event is the recommended way.
  139.                 if( g_nProgramState != PS_SPLASH )
  140.                 {
  141.                     ReceiveMessages();
  142.                     LobbyMessageReceive(LMR_PROPERTIES);
  143.                 }
  144.  
  145.                 // update screen
  146.                 if( !UpdateFrame() )
  147.                     ExitGame();     // posts QUIT msg
  148.             }
  149.         }
  150.         else
  151.         {
  152.             // Any windows messages ? (blocks until a message arrives)
  153.             if( !GetMessage( &msg, NULL, 0, 0 ) )
  154.                 break;
  155.  
  156.             TranslateMessage( &msg );
  157.             DispatchMessage( &msg );
  158.         }
  159.     }
  160.  
  161.     CoUninitialize();
  162.  
  163.     // Write information to the registry
  164.     WriteRegKey( g_hDuelKey, "Player Name", g_strLocalPlayerName );
  165.     WriteRegKey( g_hDuelKey, "Session Name", g_strSessionName );
  166.     WriteRegKey( g_hDuelKey, "Preferred Provider", g_strPreferredProvider );
  167.  
  168.     return (int)msg.wParam;
  169. }
  170.  
  171.  
  172.  
  173.  
  174. //-----------------------------------------------------------------------------
  175. // Name: MainWndproc()
  176. // Desc: Callback for all Windows messages
  177. //-----------------------------------------------------------------------------
  178. LRESULT CALLBACK MainWndproc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
  179. {
  180.     PAINTSTRUCT ps;
  181.     HDC         hdc;
  182.  
  183.     switch( msg )
  184.     {
  185.         case WM_SIZE:
  186.         case WM_MOVE:
  187.             // Get the client rectangle
  188.             if( g_bFullscreen )
  189.             {
  190.                 SetRect( &g_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN),
  191.                          GetSystemMetrics(SM_CYSCREEN) );
  192.             }
  193.             else
  194.             {
  195.                 GetClientRect( hWnd, &g_rcWindow );
  196.                 ClientToScreen( hWnd, (POINT*)&g_rcWindow );
  197.                 ClientToScreen( hWnd, (POINT*)&g_rcWindow+1 );
  198.             }
  199.             break;
  200.  
  201.         case WM_ACTIVATE:
  202.             // Ignore this message during reinitializing graphics
  203.             if( g_bReinitialize )
  204.                 return 0;
  205.  
  206.             // When we are deactivated, although we don't update our screen, we
  207.             // still need to to empty our receive queue periodically as
  208.             // messages will pile up otherwise. Polling the receive queue
  209.             // continuously even when we are deactivated causes our app to
  210.             // consume all the CPU time. To avoid hogging the CPU, we block on
  211.             // GetMessage() WIN API and setup a timer to wake ourselves up at
  212.             // regular intervals to process our messages.
  213.  
  214.             if( LOWORD(wParam) == WA_INACTIVE )
  215.             {
  216.                 // Aeactivated
  217.                 g_bIsActive = FALSE;
  218.                 if( PS_ACTIVE == g_nProgramState )
  219.                     SetTimer( hWnd, RECEIVE_TIMER_ID, RECEIVE_TIMEOUT, NULL );
  220.             }
  221.             else
  222.             {
  223.                 // Activated
  224.                 g_bIsActive = TRUE;
  225.                 if( PS_ACTIVE == g_nProgramState )
  226.                     KillTimer( hWnd, RECEIVE_TIMER_ID );
  227.             }
  228.  
  229.             // set game palette, if activated in game mode
  230.             if( g_bIsActive && (g_nProgramState != PS_SPLASH) )
  231.                 SetGamePalette();
  232.  
  233.             DIUtil_ReacquireInputDevices();
  234.  
  235.             return 0;
  236.  
  237.         case WM_CREATE:
  238.             break;
  239.  
  240.         case WM_SYSKEYUP:
  241.             switch( wParam )
  242.             {
  243.                 // Handle ALT+ENTER (fullscreen/window mode)
  244.                 case VK_RETURN:
  245.                     // Mode switch is allowed only during the game
  246.                     if( g_nProgramState == PS_ACTIVE )
  247.                     {
  248.                         g_bReinitialize = TRUE;
  249.                         ReleaseLocalData();  //only sound buffers have to be rels'd anyway.
  250.                         CleanupGameSounds();
  251.                         DIUtil_CleanupInput();
  252.                         CleanupGraphics();
  253.                         DestroyWindow( g_hwndMain );
  254.                         g_bFullscreen = !g_bFullscreen;
  255.                         InitGraphics();
  256.                         DIUtil_InitInput( g_hwndMain );
  257.                         InitializeGameSounds();
  258.                         InitLocalSoundData();
  259.                         g_bReinitialize = FALSE;
  260.                     }
  261.                     break;
  262.             }
  263.             break;
  264.  
  265.         case WM_KEYDOWN:
  266.             switch( wParam )
  267.             {
  268.                 case 'a':
  269.                 case 'A':
  270.                     // Toggle Async sends on/off
  271.                     if( g_bAsyncSupported )
  272.                     {
  273.                         g_bAsync = !g_bAsync;
  274.                         UpdateTitle();      // caption bar status
  275.                     }
  276.                     break;
  277.  
  278.                 case 'r':
  279.                 case 'R':
  280.                     // Toggle reliable sends
  281.                     g_bReliable = !g_bReliable;
  282.                     UpdateTitle();
  283.                     break;
  284.  
  285.                 case VK_F1:
  286.                     // Display help
  287.                     DoHelp();
  288.                     break;
  289.  
  290.                 case VK_F5:
  291.                     // Toggle frame rate display
  292.                     g_bShowFrameCount = !g_bShowFrameCount;
  293.                     if( g_bShowFrameCount )
  294.                     {
  295.                         g_dwFrameCount = 0;
  296.                         g_dwFrameTime = timeGetTime();
  297.                     }
  298.                     break;
  299.  
  300.                 case VK_RETURN:
  301.                     // Launch game setup wizard
  302.                     if( (g_nProgramState == PS_SPLASH) && !g_bFullscreen )
  303.                     {
  304.                         int nExitCode;
  305.                         nExitCode = DPConnect_StartDirectPlayConnect( g_hInst, FALSE );
  306.  
  307.                         // Figure out what happened, and post a reflecting message
  308.                         if( nExitCode == EXITCODE_FORWARD )
  309.                             PostMessage(g_hwndMain, UM_LAUNCH, 0, 0);
  310.  
  311.                         if( nExitCode == EXITCODE_QUIT )
  312.                             PostMessage(g_hwndMain, UM_ABORT, 0, 0);
  313.  
  314.                         if( nExitCode == EXITCODE_LOBBYCONNECT )
  315.                             PostMessage( g_hwndMain, UM_LAUNCH, 0, 0 );
  316.  
  317.                         if( nExitCode == EXITCODE_ERROR )
  318.                         {
  319.                             MessageBox( g_hwndMain, TEXT("Mutliplayer connect failed. "
  320.                                         "The sample will now quit."),
  321.                                         TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
  322.                             PostMessage(g_hwndMain, UM_ABORT, 0, 0);
  323.                         }
  324.                     }
  325.                     break;
  326.  
  327.                 case VK_ESCAPE:
  328.                 case VK_F12:
  329.                     // Exit the game
  330.                     ExitGame();
  331.                     return 0;
  332.             }
  333.             break;
  334.  
  335.         case WM_PAINT:
  336.             hdc = BeginPaint( hWnd, &ps );
  337.             if( g_nProgramState == PS_SPLASH )
  338.             {
  339.                 // Display the splash screen
  340.                 BltSplashScreen( NULL );
  341.             }
  342.  
  343.             EndPaint( hWnd, &ps );
  344.             return 1;
  345.  
  346.         case UM_LAUNCH:
  347.         case UM_ABORT:
  348.             // if we were launched by the lobby and not (failed to finish a lobby launch)
  349.             // where wParam is bLobbyLaunched
  350.             if( msg == UM_LAUNCH )
  351.             {
  352.                 // Init lobby msg support for reporting score
  353.                 // Note that we don't release the lobby object
  354.                 LobbyMessageInit();
  355.  
  356.                 // Start the game in rest mode
  357.                 g_nProgramState = PS_REST;
  358.                 LaunchGame();
  359.                 return 1;
  360.             }
  361.             // Else aborting
  362.             ExitGame();
  363.             return 1;
  364.  
  365.         case WM_TIMER:
  366.             ReceiveMessages();
  367.             LobbyMessageReceive( LMR_PROPERTIES );
  368.             break;
  369.  
  370.         case WM_DESTROY:
  371.             // If g_bReinitialize is TRUE don't quit, we are just switching
  372.             // display modes
  373.             if( !g_bReinitialize )
  374.             {
  375.                 CleanupApplication();
  376.                 PostQuitMessage( 0 );
  377.             }
  378.             return 0;
  379.  
  380.         default:
  381.             break;
  382.     }
  383.  
  384.     return DefWindowProc( hWnd, msg, wParam, lParam );
  385. }
  386.  
  387.  
  388.  
  389. //-----------------------------------------------------------------------------
  390. // Name: InitApplication()
  391. // Desc: Do that initialization stuff...
  392. //-----------------------------------------------------------------------------
  393. HRESULT InitApplication( HINSTANCE hInst )
  394. {
  395.     WNDCLASS wndClass = { CS_DBLCLKS, MainWndproc, 0, 0, hInst,
  396.                           LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN)),
  397.                           LoadCursor(NULL, IDC_ARROW), 
  398.                           (HBRUSH)GetStockObject(BLACK_BRUSH),
  399.                           NULL, TEXT("DuelClass") };
  400.     RegisterClass( &wndClass );
  401.  
  402.     // Initialize all components
  403.     if( FAILED( InitGraphics() ) )
  404.         return E_FAIL;
  405.     
  406.     if( FAILED( DIUtil_InitInput( g_hwndMain ) ) )
  407.         return E_FAIL;
  408.  
  409.     if( FAILED( InitializeGameSounds() ) )
  410.     {
  411.         // Can play game without sound. Do not exit
  412.     }
  413.  
  414.     // Start in splash mode
  415.     g_nProgramState = PS_SPLASH;
  416.  
  417.     return S_OK;
  418. }
  419.  
  420.  
  421.  
  422.  
  423. //-----------------------------------------------------------------------------
  424. // Name: CleanupApplication()
  425. // Desc: Calls clean up on all components
  426. //-----------------------------------------------------------------------------
  427. VOID CleanupApplication()
  428. {
  429.     CleanupComm();
  430.     CleanupGameSounds();
  431.     CleanupGraphics();
  432.     DIUtil_CleanupInput();
  433.     DPLobbyRelease();               // in case we were doing lobby messages
  434. }
  435.  
  436.  
  437.  
  438.  
  439. //-----------------------------------------------------------------------------
  440. // Name: ShowError()
  441. // Desc: Displays error to the user
  442. //-----------------------------------------------------------------------------
  443. VOID ShowError( int iStrID )
  444. {
  445.     TCHAR strMsg[MAX_ERRORMSG];
  446.     LoadString( g_hInst, iStrID, strMsg, MAX_ERRORMSG );
  447.     MessageBox( g_hwndMain, strMsg, TEXT("Duel Message"), MB_OK );
  448. }
  449.  
  450.  
  451.  
  452.  
  453. //-----------------------------------------------------------------------------
  454. // Name: UpdateTitle()
  455. // Desc: Updates the window title based on application status
  456. //-----------------------------------------------------------------------------
  457. VOID UpdateTitle()
  458. {
  459.     // Build the window title
  460.     TCHAR strTitle[MAX_WINDOWTITLE] = TEXT("Duel");
  461.  
  462.     // State options in window title
  463.     if( g_bHostPlayer | g_bUseProtocol | g_bReliable | g_bAsync )
  464.     {   
  465.         strcat( strTitle, " - |" );
  466.         if( g_bHostPlayer )
  467.             _tcscat( strTitle, TEXT(" Host |") );
  468.         if( g_bUseProtocol )
  469.             _tcscat( strTitle, TEXT(" Protocol |") );
  470.         if( g_bReliable )
  471.             _tcscat( strTitle, TEXT(" Reliable |") );
  472.         if( g_bAsync )
  473.             _tcscat( strTitle, TEXT(" Async |") );
  474.     }
  475.  
  476.     // Change window title
  477.     SetWindowText( g_hwndMain, strTitle );
  478. }
  479.  
  480.  
  481.  
  482.  
  483. //-----------------------------------------------------------------------------
  484. // Name: DoHelp()
  485. // Desc: Display a Help summary in a message box.
  486. //-----------------------------------------------------------------------------
  487. VOID DoHelp()
  488. {
  489.     TCHAR strHelpMsg[MAX_HELPMSG];
  490.     LoadString( g_hInst, IDS_DUEL_HELP, strHelpMsg, MAX_HELPMSG );
  491.     MessageBox( g_hwndMain, strHelpMsg, TEXT("DUEL"), MB_OK );
  492. }
  493.  
  494.  
  495.  
  496.  
  497. //-----------------------------------------------------------------------------
  498. // Name: ReadRegKey()
  499. // Desc: Read a registry key 
  500. //-----------------------------------------------------------------------------
  501. HRESULT ReadRegKey( HKEY hKey, TCHAR* strName, TCHAR* strValue, 
  502.                     DWORD dwLength, TCHAR* strDefault )
  503. {
  504.     DWORD dwType;
  505.     LONG bResult;
  506.  
  507.     bResult = RegQueryValueEx( hKey, strName, 0, &dwType, 
  508.                              (LPBYTE) strValue, &dwLength );
  509.     if ( bResult != ERROR_SUCCESS )
  510.         strcpy( strValue, strDefault );
  511.  
  512.     return S_OK;
  513. }
  514.  
  515.  
  516.  
  517.  
  518. //-----------------------------------------------------------------------------
  519. // Name: WriteRegKey()
  520. // Desc: Writes a registry key 
  521. //-----------------------------------------------------------------------------
  522. HRESULT WriteRegKey( HKEY hKey, TCHAR* strName, TCHAR* strValue )
  523. {
  524.     LONG bResult;
  525.  
  526.     bResult = RegSetValueEx( hKey, strName, 0, REG_SZ, 
  527.                              (LPBYTE) strValue, strlen(strValue) + 1 );
  528.     if ( bResult != ERROR_SUCCESS )
  529.         return E_FAIL;
  530.  
  531.     return S_OK;
  532. }
  533.  
  534.